#ifndef WOLF_EVENT_TEST_HPP
#define WOLF_EVENT_TEST_HPP

#include "wolf_test.hpp
#include <SDL_ttf.h>

namespace wolf
{
    //    typedef void (*funcpoint)(int, int);
    /**
     * @brief Tests the Engine's event handling.
     *
     * It creates:
     *  - A quit handler that prints a goodbye text on stdout.
     *  - A draw handler that prints a hello world text on screen.
     *  - A key handler that print the last key down and last up and if a key that still pressed.
     *  - A mouse handler that print the position of last click and the current position.
     *
     **/
    class EventTest : public Test
    {
    public:
        TTF_Font *_font; ///< A font
        static EventTest *_this; ///< Don't do it at home! Just to test!!! It indicates the active test instance.
        /**
         * @brief Creates a new engine event test
         *
         *
         **/
        EventTest() : Test("Event Handling System")
        {
            _font = TTF_OpenFont("resource/larabieb.ttf", 20);
            _this = this;
        }
        ~EventTest()
        {
            TTF_CloseFont(_font);
        }

        bool run()
        {
            Engine engine( Engine::RELEASE );
            engine.setVideoMode( 640, 480, 0 );
            engine.setFrameRate( 30 );

            //Setting the handlers
            engine.addQuitHandler(myQuitHandler);
            engine.addKeyDownHandler(myKDHandler);
            engine.addKeyUpHandler(myKUHandler);
            engine.addFrameHandler(myFrameHandler);
            engine.addDrawHandler(myDrawHandler);
            engine.addMouseMoveHandler(myMMHandler);
            engine.addMouseButtonUpHandler(myMBUHandler);
            engine.addMouseButtonDownHandler(myMBDHandler);
            engine.addManager(myEventHandler);

            //Starting the engine
            engine.start();
            while( engine.isRunning() )
            {
                engine.doFrame();
            }

            engine.halt();
            return true;
        }

        /**
         * @brief Handles a quit event
         *
         * @param engine The engine itself
         * @return False when the turn off should be stop. True if it has to proceed.
         **/
        static bool myQuitHandler(Engine &engine)
        {
            cout << "Turning off at frame #" << engine.getCurrentFrame() << endl;
            return true;
        }

        /**
         * @brief Handles a KeyDown Event
         *
         * @param engine the engine itself
         * @param key A sdl keysym containing information about the key
         **/
        static bool myKDHandler(Engine &engine, const SDL_keysym &key)
        {
            cout << "Key Down: " << SDL_GetKeyName(key.sym) << endl;
            if(key.sym == SDLK_ESCAPE) engine.end();
            return true;
        }

        /**
         * @brief Handles a KeyUp Event
         *
         * @param engine the engine itself
         * @param key A sdl keysym containing information about the key
         **/
        static bool myKUHandler(Engine &engine, const SDL_keysym &key)
        {
            cout << "Key Up: " << SDL_GetKeyName(key.sym) << endl;
            return true;
        }

        /**
         * @brief Handles a Frame
         *
         * Occurs once a frame.
         * @param engine The engine itself
         **/
        static void myFrameHandler(Engine &engine)
        {
            if(engine.getCurrentFrame() % 30 == 0)
            {
                cout << "A game second passed. FrameCount"<< engine.getCurrentFrame() << " TickCount: " << SDL_GetTicks() << endl;
                int size;
                Uint8 *keys = engine.getKeyState(&size);
                for(int i= 0; i < size; ++i)
                {
                    if(keys[i])
                    {
                        cout << "\tThe key '" << SDL_GetKeyName((SDLKey)i) << "' is pressed" << endl;
                    }
                }
                cout << endl;
            }
        }

        /**
         * @brief Handles Drawing
         *
         * @param engine The engine itself
         * @param screen The dst screen.
         **/
        static void myDrawHandler(Engine &engine, SDL_Surface *screen)
        {
            SDL_Surface *text = TTF_RenderUTF8_Blended(_this->_font, "Olá galera!", (SDL_Color){255,255,255});
            SDL_Rect r= {100,100};
            SDL_BlitSurface(text, NULL, screen, &r);
        }

        /**
         * @brief handles Mouse moving
         *
         * @param engine The engine that called it
         * @param state The state of mouse buttons
         * @param x The current x
         * @param y The current y
         * @param xrel The relative x
         * @param yrel The relative y
         * @return allways true
         **/
        static bool myMMHandler(Engine &engine, Uint8 state, Uint16 x, Uint16 y, Sint16 xrel, Sint16 yrel)
        {
            cout << "Moved x: " << xrel << "; y: "<< yrel<<endl;
            return true;
        }

        /**
         * @brief Handles mouse button down
         *
         * @param engine The engine that called it
         * @param button The button pressed
         * @param x The current x
         * @param y The current y
         * @return allways true
         **/
        static bool myMBDHandler(Engine &engine, Uint8 button, Uint16 x, Uint16 y)
        {
            cout << "Mouse button pressed" << endl;
            return true;
        }

        /**
         * @brief Handles mouse button up
         *
         * @param engine The engine that called it
         * @param button The button released
         * @param x The current x
         * @param y The current y
         * @return allways true
         **/
        static bool myMBUHandler(Engine &engine, Uint8 button, Uint16 x, Uint16 y)
        {
            cout << "Mouse button released" << endl;
            return true;
        }

        /**
         * @brief Handles all event types
         *
         * All event not handled by others is handled here. Be careful that
         * the list may change on future, when new events become supported
         **/
        static bool myEventHandler(Engine &engine, const SDL_Event &event)
        {
            cout << "An event happened!" << int(event.type) << endl;
            return true;
        }
    };

    EventTest *EventTest::_this = NULL;

}

#endif // WOLF_EVENT_TEST_HPP

